package com.spring.jackson.seckill.mq.handler;

import com.spring.jackson.message.AbstarctMessageHandler;
import com.spring.jackson.seckill.cache.GoodsRedisStoreCache;
import com.spring.jackson.seckill.cache.SeckillFinishCache;
import com.spring.jackson.seckill.cache.SeckillSuccessTokenCache;
import com.spring.jackson.seckill.constant.MessageType;
import com.spring.jackson.seckill.mq.message.SeckillRequestMessage;
import com.spring.jackson.smvc.exception.BusinessException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class SeckillRequestHandler extends AbstarctMessageHandler<SeckillRequestMessage> {

    private static Log logger = LogFactory.getLog(SeckillRequestHandler.class);

    @Autowired
    private SeckillSuccessTokenCache seckillSuccessTokenCache;
    @Autowired
    private GoodsRedisStoreCache goodsRedisStoreCache;

    @Autowired
    private SeckillFinishCache seckillFinishCache;

    /**
     * 这里的MessageType.MIAOSHA_MESSAGE相当于rabbitMQ队列名称，启动时就注册进去并且监听
     */
    public SeckillRequestHandler() {
        // 说明该handler监控的消息类型；失败重试次数设定为MAX_VALUE
        super(MessageType.MIAOSHA_MESSAGE, SeckillRequestMessage.class, Integer.MAX_VALUE);
    }

    /**
     * 监听并且消费了后，会调用此处，这里可以做别的业务逻辑
     *
     * @param seckillRequestMessage
     */
    public void handle(SeckillRequestMessage seckillRequestMessage) {
        System.out.println("消费掉了：" + seckillRequestMessage.getGoodsRandomName());

        // 先看抢购是否已经结束了
        if (seckillFinishCache.isFinish(seckillRequestMessage.getGoodsRandomName())) {
            logger.error("抱歉，您来晚了，抢购已经结束了");
            return;
        }

        // 先减redis库存
        if (!goodsRedisStoreCache.decrStore(seckillRequestMessage.getGoodsRandomName())) {
            // 减库存失败
            throw new BusinessException("占redis名额失败，等待重试");
        }

        // 减库存成功：生成下单token，并存入redis供前端获取
        String token = seckillSuccessTokenCache.genToken(seckillRequestMessage.getMobile(), seckillRequestMessage.getGoodsRandomName());

        System.out.println("生成下单Token:" + token);
    }

    /**
     * 监听到消息并且异常，超过失败次数，停止重试时会调用此处，然后可以做别的事情，记录失败的等
     *
     * @param seckillRequestMessage
     */
    public void handleFailed(SeckillRequestMessage seckillRequestMessage) {
        StringBuilder sb = new StringBuilder();
        sb.append("msg:[").append(seckillRequestMessage).append("], 超过失败次数，停止重试。");
        logger.warn(sb.toString());
    }


}
